################################################################################
#
#Copyright (c) 2011, Petr Skramovsky
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL Petr Skramovsky BE LIABLE FOR ANY
#DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################

svc_bad = 0
svc_NOP = 1
svc_gamestate = 2
svc_configstring = 3
svc_baseline = 4
svc_serverCommand = 5
svc_download = 6
svc_snapshot = 7
svc_EOF = 8

MAX_CLIENTS	=	64
MAX_LOCATIONS	=	64

GENTITYNUM_BITS	=	10
MAX_GENTITIES	=	(1 << GENTITYNUM_BITS)

ENTITYNUM_NONE	=	(MAX_GENTITIES-1)
ENTITYNUM_WORLD	=	(MAX_GENTITIES-2)
ENTITYNUM_MAX_NORMAL = (MAX_GENTITIES-2)


MAX_MODELS	=	256
MAX_SOUNDS	=	256


MAX_CONFIGSTRINGS	= 1024


CS_SERVERINFO	=	0
CS_SYSTEMINFO	=	1

RESERVED_CONFIGSTRINGS =	2

MAX_GAMESTATE_CHARS	= 16000;

MAX_CONFKEY = 256
MAX_CONFVAR = 3024
MAP_RESTART_DURATION  = 400
MSG_START_TIME = 1000
CS_WARMUP_END = 13
CS_PAUSE_START = 669
CS_PAUSE_COUNTDOWN = 670
CS_CA_ROUND_COUNTDOWN  = 661
CS_CA_ROUND_START = 662
CS_PLAYERS = 544
CS_PLAYERS_QZ = 529
CPMA_GAMEINFO = 672
CS_WARMUP			=	5

PACKET_BACKUP	= 32
PACKET_MASK	=	(PACKET_BACKUP-1)
MAX_PARSE_ENTITIES	= 2048

TR_STATIONARY = 0
TR_INTERPOLATE = 1
TR_LINEAR = 2
TR_LINEAR_STOP = 3
TR_SINE = 4
TR_GRAVITY = 5

FLOAT_INT_BITS = 13
FLOAT_INT_BIAS = ( 1 << ( FLOAT_INT_BITS - 1 ) )
MAX_MAP_AREA_BYTES = 32
MAX_PS_EVENTS = 2

MAX_STATS = 16
MAX_PERSISTANT = 16
MAX_POWERUPS = 16
MAX_WEAPONS = 16

PACKET_BACKUP	= 32
PACKET_MASK = ( PACKET_BACKUP - 1 )

class trajectory():
  def __init__(self):
    self.trType = 0
    self.trTime = 0
    self.rDuration = 0
    self.trBase = [ 0 ] * 3
    self.trDelta = [ 0 ] * 3

  def __str__(self):
    vars = ( self.trType,
    self.trTime,
    self.rDuration,
    self.trBase,
    self.trDelta)
    ret = "trajectory : ("
    for v in vars:
      ret += str( v ) + " "
    ret += ")"
    return ret

class trajectoryQz():
  def __init__(self):
    self.trType = 0
    self.trTime = 0
    self.rDuration = 0
    self.trBase = [ 0 ] * 3
    self.trDelta = [ 0 ] * 3
    self.gravity = 0

  def __str__(self):
    vars = ( self.trType,
    self.trTime,
    self.rDuration,
    self.trBase,
    self.trDelta,
    self.gravity )
    ret = "trajectory : ("
    for v in vars:
      ret += str( v ) + " "
    ret += ")"
    return ret


class playerState():
  def __init__(self):
    self.commandTime = 0
    self.pm_type = 0
    self.bobCycle = 0
    self.pm_flags = 0
    self.pm_time = 0
    self.origin = [ 0 ] * 3
    self.velocity = [ 0 ] * 3
    self.weaponTime = 0
    self.gravity = 0
    self.speed = 0
    self.delta_angles = [ 0 ] * 3
    self.groundEntityNum = 0
    self.legsTimer = 0
    self.legsAnim = 0
    self.torsoTimer = 0
    self.torsoAnim = 0
    self.movementDir = 0
    self.grapplePoint = [ 0 ] * 3
    self.eFlags = 0
    self.eventSequence = 0
    self.events = [ 0 ] * MAX_PS_EVENTS
    self.eventParms = [ 0 ] * MAX_PS_EVENTS
    self.externalEvent = 0
    self.externalEventParm = 0
    self.externalEventTime = 0
    self.clientNum = 0
    self.weapon = 0
    self.weaponstate = 0
    self.viewangles = [ 0 ] * 3
    self.viewheight = 0
    self.damageEvent = 0
    self.damageYaw = 0
    self.damagePitch = 0
    self.damageCount = 0
    self.stats = [ 0 ] * MAX_STATS
    self.persistant = [ 0 ] * MAX_PERSISTANT
    self.powerups = [ 0 ] * MAX_POWERUPS
    self.ammo = [ 0 ] * MAX_WEAPONS
    self.generic1 = 0
    self.loopSound = 0
    self.jumppad_ent = 0
    self.ping = 0
    self.pmove_framecount = 0
    self.jumppad_frame = 0
    self.entityEventSequence = 0

  def __str__(self):
    vars = ( self.commandTime,
    self.pm_type,
    self.bobCycle,
    self.pm_flags,
    self.pm_time,
    self.origin,
    self.velocity,
    self.weaponTime,
    self.gravity,
    self.speed,
    self.delta_angles,
    self.groundEntityNum,
    self.legsTimer,
    self.legsAnim,
    self.torsoTimer,
    self.torsoAnim,
    self.movementDir,
    self.grapplePoint,
    self.eFlags,
    self.eventSequence,
    self.events,
    self.eventParms,
    self.externalEvent,
    self.externalEventParm,
    self.externalEventTime,
    self.clientNum,
    self.weapon,
    self.weaponstate,
    self.viewangles,
    self.viewheight,
    self.damageEvent,
    self.damageYaw,
    self.damagePitch,
    self.damageCount,
    self.stats,
    self.persistant,
    self.powerups,
    self.ammo,
    self.generic1,
    self.loopSound,
    self.jumppad_ent,
    self.ping,
    self.pmove_framecount,
    self.jumppad_frame,
    self.entityEventSequence )

    ret = ""
    for v in vars:
      ret += str( v ) + " "

    return ret

class playerStateNETF():
  def __init__( self, player ):
    self.player = player
    self.fields = [ 0 ] * 48
    self.bits = []
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( -16 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( -16 )
    self.bits.append( 16 )
    self.bits.append( 8 )
    self.bits.append( 4 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 16 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 4 )
    self.bits.append( 16 )
    self.bits.append( 10 )
    self.bits.append( 16 )
    self.bits.append( 16 )
    self.bits.append( 16 )
    self.bits.append( 8 )
    self.bits.append( -8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 16 )
    self.bits.append( 16 )
    self.bits.append( 12 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 5 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 10 )
    self.bits.append( 16 )

    assert len( self.bits ) == len( self.fields )

  def __setitem__(self,index,value):
    self.fields[ index ] = value

  def __getitem__(self,index):
    return self.fields[ index ]
    
  def update(self):
    self.player.commandTime = self.fields[ 0 ]
    self.player.origin[ 0 ] = self.fields[ 1 ]
    self.player.origin[ 1 ] = self.fields[ 2 ]
    self.player.bobCycle = self.fields[ 3 ]
    self.player.velocity[ 0 ] = self.fields[ 4 ]
    self.player.velocity[ 1 ] = self.fields[ 5 ]
    self.player.viewangles[ 1 ] = self.fields[ 6 ]
    self.player.viewangles[ 0 ] = self.fields[ 7 ]
    self.player.weaponTime = self.fields[ 8 ]
    self.player.origin[ 2 ] = self.fields[ 9 ]
    self.player.velocity[ 2 ] = self.fields[ 10 ]
    self.player.legsTimer = self.fields[ 11 ]
    self.player.pm_time = self.fields[ 12 ]
    self.player.eventSequence = self.fields[ 13 ]
    self.player.torsoAnim = self.fields[ 14 ]
    self.player.movementDir = self.fields[ 15 ]
    self.player.events[ 0 ] = self.fields[ 16 ]
    self.player.legsAnim = self.fields[ 17 ]
    self.player.events[ 1 ] = self.fields[ 18 ]
    self.player.pm_flags = self.fields[ 19 ]
    self.player.groundEntityNum = self.fields[ 20 ]
    self.player.weaponstate = self.fields[ 21 ]
    self.player.eFlags = self.fields[ 22 ]
    self.player.externalEvent = self.fields[ 23 ]
    self.player.gravity = self.fields[ 24 ]
    self.player.speed = self.fields[ 25 ]
    self.player.delta_angles[ 1 ] = self.fields[ 26 ]
    self.player.externalEventParm = self.fields[ 27 ]
    self.player.viewheight = self.fields[ 28 ]
    self.player.damageEvent = self.fields[ 29 ]
    self.player.damageYaw = self.fields[ 30 ]
    self.player.damagePitch = self.fields[ 31 ]
    self.player.damageCount = self.fields[ 32 ]
    self.player.generic1 = self.fields[ 33 ]
    self.player.pm_type = self.fields[ 34 ]
    self.player.delta_angles[ 0 ] = self.fields[ 35 ]
    self.player.delta_angles[ 2 ] = self.fields[ 36 ]
    self.player.torsoTimer = self.fields[ 37 ]
    self.player.eventParms[ 0 ] = self.fields[ 38 ]
    self.player.eventParms[ 1 ] = self.fields[ 39 ]
    self.player.clientNum = self.fields[ 40 ]
    self.player.weapon = self.fields[ 41 ]
    self.player.viewangles[ 2 ] = self.fields[ 42 ]
    self.player.grapplePoint[ 0 ] = self.fields[ 43 ]
    self.player.grapplePoint[ 1 ] = self.fields[ 44 ]
    self.player.grapplePoint[ 2 ] = self.fields[ 45 ]
    self.player.jumppad_ent = self.fields[ 46 ]
    self.player.loopSound = self.fields[ 47 ]

class clSnapshot():
  def __init__(self):
    self.valid = False
    self.snapFlags = 0
    self.serverTime = 0
    self.messageNum = 0
    self.deltaNum = 0
    self.ping = 0
    self.areamask = [ 0 ] * MAX_MAP_AREA_BYTES
    self.cmdNum = 0
    self.ps = None
    self.numEntities = 0
    self.parseEntitiesNum = 0
    self.serverCommandNum = 0

class entityState():
  def __init__(self):
    self.number = 0
    self.eType = 0
    self.eFlags = 0
    self.pos = trajectory()
    self.apos = trajectory()
    self.time = 0
    self.time2 = 0
    self.origin = [ 0 ] * 3
    self.origin2 = [ 0 ] * 3
    self.angles = [ 0 ] * 3
    self.angles2 = [ 0 ] * 3
    self.otherEntityNum = 0
    self.otherEntityNum2 = 0
    self.groundEntityNum = 0
    self.constantLight = 0
    self.loopSound = 0
    self.modelindex = 0
    self.modelindex2 = 0
    self.clientNum = 0
    self.frame = 0
    self.solid = 0
    self.event = 0
    self.eventParm = 0
    self.powerups = 0
    self.weapon = 0
    self.legsAnim = 0
    self.torsoAnim = 0
    self.generic1 = 0

  def __str__( self ):
      vars = ( self.number,
      self.eType,
      self.eFlags,
      self.pos,
      self.apos,
      self.time,
      self.time2,
      self.origin,
      self.origin2,
      self.angles,
      self.angles2,
      self.otherEntityNum,
      self.otherEntityNum2,
      self.groundEntityNum,
      self.constantLight,
      self.loopSound,
      self.modelindex,
      self.modelindex2,
      self.clientNum,
      self.frame,
      self.solid,
      self.event,
      self.eventParm,
      self.powerups,
      self.weapon,
      self.legsAnim,
      self.torsoAnim,
      self.generic1 )

      ret = ""
      for v in vars:
        ret += str( v ) + " "

      return ret

class entityStateNETF():
  def __init__(self,entity):
    self.entity = entity
    self.fields = [ 0 ] * 51
    self.bits = []
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 10 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 19 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 24 )
    self.bits.append( 16 )
    self.bits.append( 8 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 32 )
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 16 )

    assert len( self.bits ) == len( self.fields )

  def __setitem__(self,index,value):
    self.fields[ index ] = value

  def update(self):
    self.entity.pos.trTime = self.fields[ 0 ]
    self.entity.pos.trBase[ 0 ] = self.fields[ 1 ]
    self.entity.pos.trBase[ 1 ] = self.fields[ 2 ]
    self.entity.pos.trDelta[ 0 ] = self.fields[ 3 ]
    self.entity.pos.trDelta[ 1 ] = self.fields[ 4 ]
    self.entity.pos.trBase[ 2 ] = self.fields[ 5 ]
    self.entity.apos.trBase[ 1 ] = self.fields[ 6 ]
    self.entity.pos.trDelta[ 2 ] = self.fields[ 7 ]
    self.entity.apos.trBase[ 0 ] = self.fields[ 8 ]
    self.entity.event = self.fields[ 9 ]
    self.entity.angles2[ 1 ] = self.fields[ 10 ]
    self.entity.eType = self.fields[ 11 ]
    self.entity.torsoAnim = self.fields[ 12 ]
    self.entity.eventParm = self.fields[ 13 ]
    self.entity.legsAnim = self.fields[ 14 ]
    self.entity.groundEntityNum = self.fields[ 15 ]
    self.entity.pos.trType = self.fields[ 16 ]
    self.entity.eFlags = self.fields[ 17 ]
    self.entity.otherEntityNum = self.fields[ 18 ]
    self.entity.weapon = self.fields[ 19 ]
    self.entity.clientNum = self.fields[ 20 ]
    self.entity.angles[ 1 ] = self.fields[ 21 ]
    self.entity.pos.trDuration = self.fields[ 22 ]
    self.entity.apos.trType = self.fields[ 23 ]
    self.entity.origin[ 0 ] = self.fields[ 24 ]
    self.entity.origin[ 1 ] = self.fields[ 25 ]
    self.entity.origin[ 2 ] = self.fields[ 26 ]
    self.entity.solid = self.fields[ 27 ]
    self.entity.powerups = self.fields[ 28 ]
    self.entity.modelindex = self.fields[ 29 ]
    self.entity.otherEntityNum2 = self.fields[ 30 ]
    self.entity.loopSound = self.fields[ 31 ]
    self.entity.generic1 = self.fields[ 32 ]
    self.entity.origin2[ 2 ] = self.fields[ 33 ]
    self.entity.origin2[ 0 ] = self.fields[ 34 ]
    self.entity.origin2[ 1 ] = self.fields[ 35 ]
    self.entity.modelindex2 = self.fields[ 36 ]
    self.entity.angles[ 0 ] = self.fields[ 37 ]
    self.entity.time = self.fields[ 38 ]
    self.entity.apos.trTime = self.fields[ 39 ]
    self.entity.apos.trDuration = self.fields[ 40 ]
    self.entity.apos.trBase[ 2 ] = self.fields[ 41 ]
    self.entity.apos.trDelta[ 0 ] = self.fields[ 42 ]
    self.entity.apos.trDelta[ 1 ] = self.fields[ 43 ]
    self.entity.apos.trDelta[ 2 ] = self.fields[ 44 ]
    self.entity.time2 = self.fields[ 45 ]
    self.entity.angles[ 2 ] = self.fields[ 46 ]
    self.entity.angles2[ 0 ] = self.fields[ 47 ]
    self.entity.angles2[ 2 ] = self.fields[ 48 ]
    self.entity.constantLight = self.fields[ 49 ]
    self.entity.frame = self.fields[ 50 ]

class entityStateQz():
  def __init__(self):
    self.number = 0
    self.eType = 0
    self.eFlags = 0
    self.pos = trajectoryQz()
    self.apos = trajectoryQz()
    self.time = 0
    self.time2 = 0
    self.origin = [ 0 ] * 3
    self.origin2 = [ 0 ] * 3
    self.angles = [ 0 ] * 3
    self.angles2 = [ 0 ] * 3
    self.otherEntityNum = 0
    self.otherEntityNum2 = 0
    self.groundEntityNum = 0
    self.constantLight = 0
    self.loopSound = 0
    self.modelindex = 0
    self.modelindex2 = 0
    self.clientNum = 0
    self.frame = 0
    self.solid = 0
    self.event = 0
    self.eventParm = 0
    self.powerups = 0
    self.weapon = 0
    self.legsAnim = 0
    self.torsoAnim = 0
    self.generic1 = 0

  def __str__( self ):
    vars = ( self.number,
    self.eType,
    self.eFlags,
    self.pos,
    self.apos,
    self.time,
    self.time2,
    self.origin,
    self.origin2,
    self.angles,
    self.angles2,
    self.otherEntityNum,
    self.otherEntityNum2,
    self.groundEntityNum,
    self.constantLight,
    self.loopSound,
    self.modelindex,
    self.modelindex2,
    self.clientNum,
    self.frame,
    self.solid,
    self.event,
    self.eventParm,
    self.powerups,
    self.weapon,
    self.legsAnim,
    self.torsoAnim,
    self.generic1 )

    ret = ""
    for v in vars:
      ret += str( v ) + " "

    return ret

class entityStateQzNETF():
  def __init__(self,entity):
    self.entity = entity
    self.fields = [ 0 ] * 53
    self.bits = []
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 10 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 19 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 24 )
    self.bits.append( 16 )
    self.bits.append( 8 )
    self.bits.append( GENTITYNUM_BITS )
    self.bits.append( 8 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 8 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 32 )
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 32 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 0 )
    self.bits.append( 32 )
    self.bits.append( 16 )

    assert len( self.bits ) == len( self.fields )

  def __setitem__(self,index,value):
    self.fields[ index ] = value

  def update(self):
    self.entity.pos.trTime = self.fields[ 0 ]
    self.entity.pos.trBase[ 0 ] = self.fields[ 1 ]
    self.entity.pos.trBase[ 1 ] = self.fields[ 2 ]
    self.entity.pos.trDelta[ 0 ] = self.fields[ 3 ]
    self.entity.pos.trDelta[ 1 ] = self.fields[ 4 ]
    self.entity.pos.trBase[ 2 ] = self.fields[ 5 ]
    self.entity.apos.trBase[ 1 ] = self.fields[ 6 ]
    self.entity.pos.trDelta[ 2 ] = self.fields[ 7 ]
    self.entity.apos.trBase[ 0 ] = self.fields[ 8 ]
    self.entity.apos.gravity = self.fields[ 9 ]
    self.entity.event = self.fields[ 10 ]
    self.entity.angles2[ 1 ] = self.fields[ 11 ]
    self.entity.eType = self.fields[ 12 ]
    self.entity.torsoAnim = self.fields[ 13 ]
    self.entity.eventParm = self.fields[ 14 ]
    self.entity.legsAnim = self.fields[ 15 ]
    self.entity.groundEntityNum = self.fields[ 16 ]
    self.entity.pos.trType = self.fields[ 17 ]
    self.entity.eFlags = self.fields[ 18 ]
    self.entity.otherEntityNum = self.fields[ 19 ]
    self.entity.weapon = self.fields[ 20 ]
    self.entity.clientNum = self.fields[ 21 ]
    self.entity.angles[ 1 ] = self.fields[ 22 ]
    self.entity.pos.trDuration = self.fields[ 23 ]
    self.entity.apos.trType = self.fields[ 24 ]
    self.entity.origin[ 0 ] = self.fields[ 25 ]
    self.entity.origin[ 1 ] = self.fields[ 26 ]
    self.entity.origin[ 2 ] = self.fields[ 27 ]
    self.entity.solid = self.fields[ 28 ]
    self.entity.powerups = self.fields[ 29 ]
    self.entity.modelindex = self.fields[ 30 ]
    self.entity.otherEntityNum2 = self.fields[ 31 ]
    self.entity.loopSound = self.fields[ 32 ]
    self.entity.generic1 = self.fields[ 33 ]
    self.entity.origin2[ 2 ] = self.fields[ 34 ]
    self.entity.origin2[ 0 ] = self.fields[ 35 ]
    self.entity.origin2[ 1 ] = self.fields[ 36 ]
    self.entity.modelindex2 = self.fields[ 37 ]
    self.entity.angles[ 0 ] = self.fields[ 38 ]
    self.entity.time = self.fields[ 39 ]
    self.entity.apos.trTime = self.fields[ 40 ]
    self.entity.apos.trDuration = self.fields[ 41 ]
    self.entity.apos.trBase[ 2 ] = self.fields[ 42 ]
    self.entity.apos.trDelta[ 0 ] = self.fields[ 43 ]
    self.entity.apos.trDelta[ 1 ] = self.fields[ 44 ]
    self.entity.apos.trDelta[ 2 ] = self.fields[ 45 ]
    self.entity.apos.gravity = self.fields[ 46 ]
    self.entity.time2 = self.fields[ 47 ]
    self.entity.angles[ 2 ] = self.fields[ 48 ]
    self.entity.angles2[ 0 ] = self.fields[ 49 ]
    self.entity.angles2[ 2 ] = self.fields[ 50 ]
    self.entity.constantLight = self.fields[ 51 ]
    self.entity.frame = self.fields[ 52 ]

MSG = [(0, 250315),(1, 41193),(2, 6292),(3, 7106),(4, 3730),(5, 3750),(6, 6110),(7, 23283),(8, 33317),(9,6950),(10,7838),\
      (11,9714),(12,9257),(13,17259),(14,3949),(15,1778),(16,8288),(17,1604),(18,1590),(19,1663),(20,1100),(21,1213),\
      (22,1238),(23,1134),(24,1749),(25,1059),(26,1246),(27,1149),(28,1273),(29,4486),(30,2805),(31,3472),(32,21819),\
      (33,1159),(34,1670),(35,1066),(36,1043),(37,1012),(38,1053),(39,1070),(40,1726),(41,888),(42,1180),(43,850),\
      (44,960),(45,780),(46,1752),(47,3296),(48,10630),(49,4514),(50,5881),(51,2685),(52,4650),(53,3837),(54,2093),\
      (55,1867),(56,2584),(57,1949),(58,1972),(59,940),(60,1134),(61,1788),(62,1670),(63,1206),(64,5719),(65,6128),\
      (66,7222),(67,6654),(68,3710),(69,3795),(70,1492),(71,1524),(72,2215),(73,1140),(74,1355),(75,971),(76,2180),\
      (77,1248),(78,1328),(79,1195),(80,1770),(81,1078),(82,1264),(83,1266),(84,1168),(85,965),(86,1155),(87,1186),\
      (88,1347),(89,1228),(90,1529),(91,1600),(92,2617),(93,2048),(94,2546),(95,3275),(96,2410),(97,3585),(98,2504),\
      (99,2800),(100,2675),(101,6146),(102,3663),(103,2840),(104,14253),(105,3164),(106,2221),(107,1687),(108,3208),\
      (109,2739),(110,3512),(111,4796),(112,4091),(113,3515),(114,5288),(115,4016),(116,7937),(117,6031),(118,5360),\
      (119,3924),(120,4892),(121,3743),(122,4566),(123,4807),(124,5852),(125,6400),(126,6225),(127,8291),(128,23243),\
      (129,7838),(130,7073),(131,8935),(132,5437),(133,4483),(134,3641),(135,5256),(136,5312),(137,5328),(138,5370),\
      (139,3492),(140,2458),(141,1694),(142,1821),(143,2121),(144,1916),(145,1149),(146,1516),(147,1367),(148,1236),\
      (149,1029),(150,1258),(151,1104),(152,1245),(153,1006),(154,1149),(155,1025),(156,1241),(157,952),(158,1287),\
      (159,997),(160,1713),(161,1009),(162,1187),(163,879),(164,1099),(165,929),(166,1078),(167,951),(168,1656),\
      (169,930),(170,1153),(171,1030),(172,1262),(173,1062),(174,1214),(175,1060),(176,1621),(177,930),(178,1106),\
      (179,912),(180,1034),(181,892),(182,1158),(183,990),(184,1175),(185,850),(186,1121),(187,903),(188,1087),(189,920),\
      (190,1144),(191,1056),(192,3462),(193,2240),(194,4397),(195,12136),(196,7758),(197,1345),(198,1307),(199,3278),\
      (200,1950),(201,886),(202,1023),(203,1112),(204,1077),(205,1042),(206,1061),(207,1071),(208,1484),(209,1001),\
      (210,1096),(211,915),(212,1052),(213,995),(214,1070),(215,876),(216,1111),(217,851),(218,1059),(219,805),(220,1112),\
      (221,923),(222,1103),(223,817),(224,1899),(225,1872),(226,976),(227,841),(228,1127),(229,956),(230,1159),(231,950),\
      (232,7791),(233,954),(234,1289),(235,933),(236,1127),(237,3207),(238,1020),(239,927),(240,1355),(241,768),(242,1040),\
      (243,745),(244,952),(245,805),(246,1073),(247,740),(248,1013),(249,805),(250,1008),(251,796),(252,996),(253,1057),\
      (254,11457),(255,13504)]
